#include  <QFileInfo>
#include <QSettings>
#include <QDir>

#include "asyprocess.h"


AsyProcess::AsyProcess(QObject *parent)
	:QObject(parent)
{
	asyProc=new QProcess(this);
	gsProc=new QProcess(this);
//	asyProc->setWorkingDirectory(QDir::currentPath());
//	gsProc->setWorkingDirectory(QDir::currentPath());
	connect(asyProc,SIGNAL(finished(int,QProcess::ExitStatus)),
			this,SLOT(sltAsyFinished(int,QProcess::ExitStatus)));
	connect(gsProc,SIGNAL(finished(int,QProcess::ExitStatus)),
			this,SLOT(sltGsFinished(int,QProcess::ExitStatus)));
	connect(asyProc,SIGNAL(error(QProcess::ProcessError)),this,SLOT(sltAsyError(QProcess::ProcessError)));
	connect(gsProc,SIGNAL(error(QProcess::ProcessError)),this,SLOT(sltGsError(QProcess::ProcessError)));
	loadConfig();
}

AsyProcess::~AsyProcess()
{

}

QString AsyProcess::readErrorInfo()
{
	return failedStr;
}

int AsyProcess::asyErrorLineNumber()
{
	QStringList sl=failedStr.split(":",QString::SkipEmptyParts,Qt::CaseInsensitive);
	QStringList sl2=sl.at(1).split(".",QString::SkipEmptyParts,Qt::CaseInsensitive);
	return sl2.at(0).toInt()-1;
}

QString AsyProcess::asyErrorInfo()
{
	QStringList sl=failedStr.split(":",QString::SkipEmptyParts,Qt::CaseInsensitive);
	return sl.at(2);
}

void AsyProcess::transform(QString sfile,QString dfile,Type t)
{
	QString absf=QFileInfo(sfile).absoluteFilePath();
	QString absp=QFileInfo(sfile).absolutePath();

	QString abdf=QFileInfo(dfile).absoluteFilePath();
//	QString abdp=QFileInfo(dfile).absolutePath();

	asyProc->setWorkingDirectory(absp);
	gsProc->setWorkingDirectory(absp);
	descBasenmae=QFileInfo(dfile).baseName();
	QStringList curParm(asyParms);
	switch(t){
	case ASY2EPS:{
		needGS=false;
		if(QFileInfo(dfile).suffix()!="eps")
			abdf.append(".eps");
//		printf("source: %s\n",absf.toLocal8Bit().data());
//		printf("desc: %s\n",abdf.toLocal8Bit().data());
		curParm<<"-o"<<abdf<<"-outformat"<<"eps"<<absf;
		asyProc->start(asyPath,curParm);
//		printf("%s\n",curParm.join(" ").toLocal8Bit().data());
		break;
	}
	case ASY2PDF:{
		needGS=false;
		if(QFileInfo(dfile).suffix()!="pdf")
			abdf.append(".pdf");
		curParm<<"-o"<<abdf<<"-outformat"<<"pdf"<<absf;
		asyProc->start(asyPath,curParm);
		break;
	}
	case ASY2PNG:{
		transform(absf,abdf,ASY2EPS);
		needGS=true;
//		printf("in ASY2PNG\n");
		break;
	}
	case EPS2PNG:{
		QStringList gsp(gsParms);
		if(QFileInfo(dfile).suffix()!="png")
			abdf.append(".png");
		gsp<<QString("-sOutputFile=%1").arg(abdf)<<absf;
//		printf("%s %s\n",gsPath.toLocal8Bit().data(),gsp.join(" ").toLocal8Bit().data());
		gsProc->start(gsPath,gsp);
		break;
	}
	default:
		emit finished(UnknowFailed);
	}
}

void AsyProcess::loadConfig()
{
	QSettings settings;
	settings.beginGroup("Tools");
	asyPath=settings.value("Asy Path","asy").toString();
	asyParms=settings.value("Asy Parm",QStringList()).toStringList()<<"-q"<<"-noV";
//	printf("%s %s\n",asyPath.toLocal8Bit().data(),asyParms.join(" ").toLocal8Bit().data());
	gsPath=settings.value("GS Path","gs").toString();
	gsParms=settings.value("GS Parm",gsParms).toStringList()
		<<"-dSAFER"<<"-dBATCH"<<"-dNOPAUSE"<<"-dNOPAGEPROMPT"
		<<"-sDEVICE=png16m"<<"-r600"<<"-dEPSCrop";;
//	printf("%s %s\n",gsPath.toLocal8Bit().data(),gsParms.join(" ").toLocal8Bit().data());
	settings.endGroup();
}

void AsyProcess::sltAsyFinished(int exitCode,QProcess::ExitStatus exitStatus)
{
	if(exitCode==0){
		emit finished(AsyOk);
		if(needGS) {
			transform(descBasenmae+".eps",descBasenmae,EPS2PNG);
//            printf("asyFinish\n");
        }
	}else{
		failedStr=asyProc->readAllStandardError();
		emit finished(AsyFailed);
	}
}

void AsyProcess::sltGsFinished(int exitCode,QProcess::ExitStatus exitStatus)
{
	if(exitCode==0)
		emit finished(GsOk);
	else{
		failedStr=gsProc->readAllStandardError();
		emit finished(GsFailed);
	}
}

void AsyProcess::sltAsyError(QProcess::ProcessError err)
{
	switch(err){
	case QProcess::FailedToStart:
		emit error(tr("Failed to start Asy"));
		break;
	case QProcess::Crashed:
		emit error(tr("Asy crashed"));
		break;
	default:
		emit error(tr("run asy failed"));
	}

}

void AsyProcess::sltGsError(QProcess::ProcessError err)
{
	switch(err){
	case QProcess::FailedToStart:
		emit error(tr("Failed to start gs"));
		break;
	case QProcess::Crashed:
		emit error(tr("gs crashed"));
		break;
	default:
		emit error(tr("run gs failed"));
	}
}
